﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#if DOT_NET
using Microsoft.VisualStudio.TestTools.UnitTesting;
#else
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
#endif
using StyleMVVM.DependencyInjection;
using StyleMVVM.UnitTests.TestClasses.MultipleImport;

namespace StyleMVVM.UnitTests.DependencyInjection
{
	[TestClass]
	public class FluentExportConditionTests
	{
		[TestMethod]
		public void MultipleWhenConditionTest()
		{
			Bootstrapper bootstrapper = new Bootstrapper();

			bootstrapper.Container.Register<ImportIListObject>().As<ImportIListObject>().ImportProperty(x => x.ListImports);

			bootstrapper.Container.Register<TestExport1>().As<IMTestExport>().
			             WithPriority(3).When((x, y, z) => y.IsConditionDefined("Test1"));

			bootstrapper.Container.Register<TestExport2>().As<IMTestExport>().
			             WithPriority(2).When((x, y, z) => y.IsConditionDefined("Test2"));

			bootstrapper.Container.Register<TestExport3>().As<IMTestExport>().
			             WithPriority(1).When((x, y, z) => y.IsConditionDefined("Test3"));

			bootstrapper.Start();

			// Test1
			IInjectionContext injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test1");

			ImportIListObject importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport1));

			// Test2
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test2");

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport2));

			// Test3
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test3");

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport3));

			// All
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test1");
			injectionContext.DefineCondition("Test2");
			injectionContext.DefineCondition("Test3");

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(3, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport1));
			Assert.IsInstanceOfType(importObject.ListImports[1], typeof(TestExport2));
			Assert.IsInstanceOfType(importObject.ListImports[2], typeof(TestExport3));

			bootstrapper.Shutdown();
		}

		[TestMethod]
		public void MultipleUnlessConditionTest()
		{
			Bootstrapper bootstrapper = new Bootstrapper();

			bootstrapper.Container.Register<ImportIListObject>().As<ImportIListObject>().ImportProperty(x => x.ListImports);

			bootstrapper.Container.Register<TestExport1>().As<IMTestExport>().
			             WithPriority(3).Unless((x, y, z) => y.IsConditionDefined("Test1"));

			bootstrapper.Container.Register<TestExport2>().As<IMTestExport>().
			             WithPriority(2).Unless((x, y, z) => y.IsConditionDefined("Test2"));

			bootstrapper.Container.Register<TestExport3>().As<IMTestExport>().
			             WithPriority(1).Unless((x, y, z) => y.IsConditionDefined("Test3"));

			bootstrapper.Start();

			// Test1
			IInjectionContext injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test2");
			injectionContext.DefineCondition("Test3");

			ImportIListObject importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport1));

			// Test2
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test1");
			injectionContext.DefineCondition("Test3");

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport2));

			// Test3
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			injectionContext.DefineCondition("Test1");
			injectionContext.DefineCondition("Test2");

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(1, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport3));

			// All
			injectionContext = bootstrapper.Container.CreateInjectionContext();

			importObject = bootstrapper.Container.LocateWithContext<ImportIListObject>(injectionContext);

			Assert.IsNotNull(importObject);
			Assert.AreEqual(3, importObject.ListImports.Count);
			Assert.IsInstanceOfType(importObject.ListImports[0], typeof(TestExport1));
			Assert.IsInstanceOfType(importObject.ListImports[1], typeof(TestExport2));
			Assert.IsInstanceOfType(importObject.ListImports[2], typeof(TestExport3));

			bootstrapper.Shutdown();
		}
	}
}